# Copyright (C) 2005-2008 G.P. Halkes
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 3, as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

# NOTE: this is my development Makefile. It is NOT to be used for regular
# compiles, but only if you want to do development on LLnextgen yourself. It is
# also totally unsupported. To compile LLnextgen, use the configure script and
# Makefile in the top-level directory.


# Kludge to allow for not including the automatically generated
# dependencies for several goals, even when more than one goal
# is specified on the command line.
NO_INCLUDE_GOALS:=checkdeps clean depclean lint clean-logs api linecount

ifdef REAL_MAKE
unexport REAL_MAKE
#========================================================================
VERSION?=debug
CC:=gcc
LLNEXTGEN?=LLnextgen
ifdef COVERAGE
	COVERAGEFLAGS:=-fprofile-arcs -ftest-coverage
else
	COVERAGEFLAGS:=
endif
ifdef ANSI
	ANSIFLAGS:=-std=$(ANSI) -pedantic
else
	ANSIFLAGS:=-std=c89 -pedantic
endif
ifeq ($(VERSION),debug)
	CFLAGS:=-Wall -W $(ANSIFLAGS) -ggdb3 -DDEBUG -Wswitch-default \
		-Wshadow -Wcast-align -Wbad-function-cast \
		-Wcast-qual -Wwrite-strings -Wstrict-prototypes \
		$(COVERAGEFLAGS) -O2
else
	CFLAGS:=-Wall -W $(ANSIFLAGS) -O2
endif
# To make sure the executable doesn't use 2.3 specific ctype stuff use:
#~ CFLAGS+=-D__NO_CTYPE
CFLAGS+=-DREGEX=POSIX
# To allow proper checking with valgrind:
CFLAGS+=-DMEM_DEBUG

NEWFLEX:=$(shell ./newFlex)

LEX_CFLAGS:=$(filter-out -Wshadow -Wswitch-default, $(CFLAGS)) -Wno-unused $(if $(NEWFLEX),-DNEWFLEX)
LDFLAGS:=
LDLIBS:=
# Note: disabled -X posix checking and  --never-interactive
# because flex 2.5.4a doesn't support them
LFLAGS:=-s $(if $(NEWFLEX),--nounistd)
# SPECIFY YOUR SOURCES ETC. HERE.
SOURCES:=main.c globals.c nonRuleAnalysis.c ruleAnalysis.c list.c \
	lexer.l grammar.g option.c scope.c argcount.c generate.c io.c os.c set.c \
	printInput.c generateCommon.c generateLLgenStyle.c traceTokens.c depend.c \
	generateTS.c freeData.c clash.c
SPECIAL_SOURCES:= clashStrings.c
# SPECIFY THE DEPENDENCY FILES TO BE AUTOGENERATED HERE!

DEPENDENCIES:=$(patsubst %, .deps/%, $(SOURCES))
#DEPENDENCIES:=$(patsubst %.c, .deps/%.c, $(filter %.c,$(SOURCES)))

all: LLnextgen

LLnextgen: $(patsubst %.c, %.o, $(filter %.c,$(SOURCES) $(SPECIAL_SOURCES))) \
		$(patsubst %.l, %.o, $(filter %.l,$(SOURCES))) \
		$(patsubst %.g, %.o, $(filter %.g,$(SOURCES)))
	$(CC) -o $@ $(CFLAGS) $(LDFLAGS) $^ $(LDLIBS)

%.c: %.l
	flex $(LFLAGS) -o$@ $<

freeData.o: freeData.c
	$(CC) -c -o $@ $(filter-out -Wcast-qual,$(CFLAGS)) $(CPPFLAGS) $<

lexer.o: lexer.c
	$(CC) -c $(CPPFLAGS) $(LEX_CFLAGS) $<

grammar.c grammar.h: grammar.g
	$(LLNEXTGEN) $<

clashStrings.c: $(filter generate%.c,$(SOURCES))
	./extractGeneratedStrings $^

clean:
	rm -rf *.o $(patsubst %.l, %.c, $(filter %.l,$(SOURCES))) Lpars.? \
		grammar.[ch] Lncor.c *.bb *.bbg *.da *.gcov .deps *.gcno *.gcda \
		$(SPECIAL_SOURCES) 2>/dev/null

# Testsuites (Not in distribution)
test: all
	cd ..; $(MAKE) test

test-%: all
	$(MAKE) -C .. $@

clean-logs:
	cd ..; $(MAKE) clean-logs

lint:
	splint -f ../splintflags $(filter-out symToText.c,$(filter-out option.c,$(filter %.c,$(SOURCES))))

argcount: argcount.c globals.o list.o option.o lexer.o
	gcc $(CLFAGS) -o $@ -DARGCOUNT_TEST argcount.c globals.o list.o option.o lexer.o

linecount:
	@echo "WARNING: this doesn't count the header files, only .c, .g, and .l files!"
	@echo "Linecounts as reported by wc -l"
	@wc -l $(SOURCES)
	@if [ `which c_count 2>/dev/null` ] && [ `which lex_count` ] ; then echo "Linecounts as reported by the SLOCCount utilities" ; ( c_count $(filter %.c %.g,$(SOURCES)) ;  lex_count $(filter %.l,$(SOURCES)) ) | ../format.sh ; fi

.PHONY: clean all test clean-logs lint api test-exhaustive test-compile linecount
.SECONDARY:lexer.c

#========================================================================
# FROM HERE ON DOWN THE RULES ARE THERE FOR AUTOMATIC DEPENDENCY
# GENERATION. THESE SHOULD NOT CONCERN YOU UNLESS NEW TYPES OF FILES
# NEED TO BE PROCESSED

ifeq ($(strip $(filter $(NO_INCLUDE_GOALS), $(MAKECMDGOALS))),)
-include $(DEPENDENCIES)
endif

# Example dependency generation. Could be moved to include files
# First check whether .deps exists and try to make it if it doesn't
# Run the compiler with the correct flags
# Remove the file if it was created empty
.deps/%.c: %.c
	@[ -d $(dir $@) ] || mkdir -p $(dir $@)
	@echo Generating dependencies for $<
	@$(CC) -MM $(CFLAGS) -E -MG -MF $@ -MT '$*.o $@' $< >/dev/null
	@[ -s $@ ] || ( rm -f $@ ; true )

.deps/%.l: %.l
	@[ -d $(dir $@) ] || mkdir -p $(dir $@)
	@echo Generating dependencies for $<
	@grep "^#" $< | $(CC) -E -MG -MM $(CFLAGS) $(CFLAGSLEX) -MF $@ -MT '$*.o $@' - >/dev/null
	@[ -s $@ ] || ( rm -f $@ ; true )

.deps/%.g: %.g
	@[ -d $(dir $@) ] || mkdir -p $(dir $@)
	@echo Generating dependencies for $<
	@$(LLNEXTGEN) --depend=file:$@,extra-targets:$@ $<
	@echo -n "$@ " >> $@ ; $(LLNEXTGEN) --depend-cpp $< | $(CC) -E -MG -MM $(CFLAGS) -MT $*.o - >> $@ 2>/dev/null
	@[ -s $@ ] || ( rm -f $@ ; true )

# Check whether all files mentioned as dependencies actually exist.
# Make will choke on these.
checkdeps:
	@deps="$(DEPENDENCIES)" ; \
	for dep in $$deps ; do \
		if ! [ -e $$dep ] ; then continue ; fi ; \
		files=`sed -r 's/.*://' $$dep | sed -r 's/\\\\[ \\t]*$$//g'`; \
		for f in $$files ; do \
			if ! [ -e $$f ] ; then \
				rm -f $$dep ; break ; \
			fi \
		done ; \
	done

# Remove all dependency files
depclean:
	rm -rf .deps

.PHONY: checkdeps depclean

else # REAL_MAKE

export REAL_MAKE=1

.PHONY: $(MAKECMDGOALS) default-target
# First remove all dependency files with non-existant files mentioned
# as dependencies. Otherwise make will choke.
$(MAKECMDGOALS) default-target:
	$(if $(strip $(filter-out $(NO_INCLUDE_GOALS),$@)),	@$(MAKE) --no-print-directory checkdeps)
	@$(MAKE) --no-print-directory $(filter-out default-target, $@)

endif # REAL_MAKE
